package com.xiguanlezz.cn.api.naming.pojo;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.xiguanlezz.cn.api.common.Constants;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author：习惯了种种
 * @CreateDate：2024/11/26 20:56
 * @Description：服务实例信息
 */
@ToString
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ServiceInfo {

    // groupName在key中的索引位置
    private static final int GROUP_POSITION = 0;
    // service name在key中的索引位置
    private static final int SERVICE_POSITION = 1;
    // 集群名称在key中的索引位置
    private static final int CLUSTER_POSITION = 2;
    // key的长度
    // 以上几个成员变量在本类的ServiceInfo(key)方法中会被用到，直接去这个方法中就能很清楚地明白这几个变量的作用
    private static final int FILE_NAME_PARTS = 3;

    private static final String DEFAULT_CHARSET = "UTF-8";

    // 配合ServiceInfoUpdateService中的定时任务使用
    @Setter
    @Getter
    private long cacheMillis = 1000L;


    // 服务名称
    @Setter
    @Getter
    private String name;
    // 组名
    @Setter
    @Getter
    private String groupName;
    // 集群名称
    @Setter
    @Getter
    private String clusters;

    // 当前ServiceInfo对象持有的所有服务实例（可能有多个相同功能的服务提供者注册到Nacos服务端）
    @Setter
    @Getter
    private List<Instance> hosts = new ArrayList<>();

    // start---校验服务端的实例是否变化时使用
    @Setter
    @Getter
    @JsonIgnore
    private String jsonFromServer = "";
    @Setter
    @Getter
    private long lastRefTime = 0L;
    // end---校验服务端的实例是否变化时使用


    public ServiceInfo(String name, String clusters) {
        this.name = name;
        this.clusters = clusters;
    }

    /**
     * 解析key，给成员变量赋值
     */
    public ServiceInfo(final String key) {
        // 将key转换为数组
        String[] keys = key.split(Constants.SERVICE_INFO_SPLITER);
        //判断数组长度是否大于等于3
        if (keys.length >= FILE_NAME_PARTS) {
            // 从数组中获得groupName
            this.groupName = keys[GROUP_POSITION];
            // 从数组中获得serviceName
            this.name = keys[SERVICE_POSITION];
            // 从数组中获得集群信息
            this.clusters = keys[CLUSTER_POSITION];
        } else if (keys.length == CLUSTER_POSITION) {
            // 走到这里意味着数组长度为2
            // 那集群信息就是空了
            this.groupName = keys[GROUP_POSITION];
            this.name = keys[SERVICE_POSITION];
            this.clusters = null;
        } else {
            throw new IllegalArgumentException("Can't parse out 'groupName',but it must not be null!");
        }
    }

    public static ServiceInfo fromKey(final String key) {
        return new ServiceInfo(key);
    }

    @JsonIgnore
    public String getKey() {
        String serviceName = getGroupedServiceName();
        return getKey(serviceName, clusters);
    }

    @JsonIgnore
    private String getGroupedServiceName() {
        String serviceName = this.name;
        if (StringUtils.isNotBlank(groupName) && !serviceName.contains(Constants.SERVICE_INFO_SPLITER)) {
            serviceName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;
        }
        return serviceName;
    }

    @JsonIgnore
    public static String getKey(String name, String clusters) {
        if (StringUtils.isNotBlank(clusters)) {
            return name + Constants.SERVICE_INFO_SPLITER + clusters;
        }
        return name;
    }

    @JsonIgnore
    public String getKeyEncoded() {
        String serviceName = getGroupedServiceName();
        try {
            serviceName = URLEncoder.encode(serviceName, DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException ignored) {
        }
        return getKey(serviceName, clusters);
    }

    public int ipCount() {
        return hosts.size();
    }

}
